Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at ways to improve our JavaScript code.
Converting Objects to Primitives
Objects can be converted to numbers with the valueOf
method.
For instance, we can write:
const obj = {
valueOf() {
return 3;
}
};
console.log(2 + obj);
then we see 5 logged.
We can so convert an object to a string with:
const obj = {
toString() {
return 'bar';
}
};
console.log('foo' + obj);
Then we get:
'foobar'
logged.
If an object has both the valueOf
and toString
methods, then it’s not obvious which one will be run.
So if we have:
const obj = {
toString() {
return "[object obj]";
},
valueOf() {
return 'bar';
}
};
console.log('foo' + obj);
Then we see 'foobar'
logged.
So we know that valueOf
will be run if both valueOf
and toString
are both present.
valueOf
is designed to be used for objects that represents numeric values like Number
objects.
For these objects, toString
and valueOf
are consistent.
They both return the string representation of a number.
Coercion to strings are far more common than coercion to numbers.
It’s best to avoid valueOf
unless the object is an abstraction of numbers.
Another kind of coercion is known as truthiness.
The ||
and &&
work with boolean values, but they can accept anything.
If a value is truthy, then they’re coerced to true
.
Otherwise, they’re falsy and they’re coerced to false
.
false
, 0, -0, “”, NaN
, null
, and undefined
are falsy.
Other values are all truthy.
The ||
operator lets us return a default value if the first operand is falsy.
For instance, instead of writing:
function point(x, y) {
if (!x) {
x = 10;
}
if (!y) {
y = 20;
}
return {
x,
y
};
}
or:
function point(x, y) {
if (typeof x === "undefined") {
x = 10;
}
if (typeof y === "undefined") {
y = 20;
}
return {
x,
y
};
}
We can write:
function point(x, y) {
x = x || 10;
y = y || 20;
return {
x,
y
};
}
The ||
operator takes all falsy values and returns the second operand if the first one is falsy.
Primitives are Better than Object Wrappers
Primitives are better than object wrappers.
JavaScript has various kinds of primitive values.
They include boolean, numbers, strings, null
and undefined
.
null
is reported as 'object'
with the typeof
operator but its defined as a separate type in the ES standard.
The JavaScript standard library also provides constructors for these objects.
So, we can write:
const s = new String("hello");
or:
const str = "hello";
We can extract a character with the square brackets.
For instance, we can write:
s[4]
and we get 'o'
.
But if have:
typeof s
it returns 'object'
.
But if we have:
typeof str
then we get 'string'
.
And if we have:
const s1 = new String("foo");
const s2 = new String("foo");
and if we write:
s1 === s2
it returns false
since the references are different.
It can only be equal to itself.
As we can see, this is a problem that we have with string wrapper objects and other primitive wrappers.
Conclusion
We shouldn’t use primitive wrapper objects.
They aren’t useful in our code.